package msghandler

import (
	"bytes"
	"fmt"
	"gitee.com/zhongguo168a/go-nodex/logx"
	"gitee.com/zhongguo168a/go-nodex/nodex"
	"gitee.com/zhongguo168a/go-nodex/nodex/server"
	"gitee.com/zhongguo168a/go-nodex/nodex/server/message"
	"gitee.com/zhongguo168a/gocodes/datax"
	"gitee.com/zhongguo168a/gocodes/myx/errorx"
)

type SocketMsgHandle struct {
	nodex.MsgHandle
	//
}

// Do 马上以非阻塞方式处理消息
func (mh *SocketMsgHandle) Do(request *server.Request) (err error) {
	var (
		msgId = request.Message.GetMsgID()
		token = request.Message.GetToken()
	)
	if request.Message.GetToken() != "" {
		request.Conn.GetProperty().Store("token", token)
	}
	router := request.Route.(*nodex.Router)
	ctx, errGetContext := mh.GetContext(request, router)
	if errGetContext != nil {
		err = errorx.Wrap(errGetContext, "get context", datax.M{"Route": msgId})
		return
	}
	args := request.Args
	var reply interface{}
	reply, newerr := router.NewReply()
	if newerr != nil {
		return errorx.Wrap(newerr, "new reply", datax.M{"Route": msgId})
	}
	request.Reply = reply

	var replyerr error
	switch router.Config.CallMode {
	case nodex.CONNECTION:
		replyerr = router.Call(ctx, args, reply)
		mh.resp(ctx, router, request, reply, replyerr)
	case nodex.GOROUTINE:
		//replyerr = router.Call(ctx, args, reply)
		//mh.resp(ctx, router, request, reply, replyerr)
		go func(goctx nodex.IContext, gorequest *server.Request) {
			goreply := gorequest.Reply
			goargs := gorequest.Args
			gorouter := gorequest.Route.(*nodex.Router)
			replyerr = gorouter.Call(goctx, goargs, goreply)

			mh.resp(goctx, gorouter, gorequest, goreply, replyerr)
		}(ctx, request)
	case nodex.CHANRPC:
		rpc := ctx.GetRPC()
		if rpc == nil {
			err = errorx.New("rpc not found: " + msgId)
			return
		}
		if !rpc.Contains(msgId) {
			err = errorx.New("rpc handler not found: " + msgId)
			return
		}
		if router.ReturnNum == 0 {
			callerr := rpc.Open().Call0(msgId, ctx, args, reply)
			if callerr != nil {
				replyerr = errorx.Wrap(callerr, "chanrpc call0", datax.M{"route": router.Config.Path})
			}
		} else {
			results, callerr := rpc.Open().Call1(msgId, ctx, args, reply)
			if callerr != nil {
				replyerr = errorx.Wrap(callerr, "chanrpc call1", datax.M{"route": router.Config.Path})
			} else {
				if results != nil {
					r1, _ := results.(error)
					replyerr = r1
				}
			}
		}
		mh.resp(ctx, router, request, reply, replyerr)
	}
	return
}

func (mh *SocketMsgHandle) resp(ctx nodex.IContext, router *nodex.Router, request *server.Request, reply interface{}, replyerr error) {
	if router.ReturnNum == 0 { //  无返回值
		if replyerr != nil {
			logx.Error(replyerr)
		}
	} else {
		requestData := request.Message.(*message.RequestMessage)
		msg := &message.ResponseMessage{
			Seq:           requestData.Seq,
			Route:         requestData.Route,
			SerializeMode: requestData.SerializeMode,
		}
		fmt.Println(">>>", requestData.Route, requestData.Seq)
		if replyerr == nil {
			buff := bytes.NewBuffer([]byte{})
			if err := message.Pack(buff, msg.SerializeMode, reply); err != nil {
				msg.Error = errorx.Wrap(err, "pack reply").Error()
			} else {
				msg.Data = buff.Bytes()
			}
		} else {
			msg.Error = replyerr.Error()
		}
		_ = request.Conn.SendMsgBuff(msg)
	}
	return
}
